package com.google.code.jcooky.rpc.compiler.java;

import static com.google.code.jcooky.rpc.compiler.StringUtils.copyOfString;
import static com.google.code.jcooky.rpc.compiler.StringUtils.read;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;

import com.google.code.jcooky.rpc.compiler.Processor;
import com.google.code.jcooky.rpc.compiler.StringUtils;

public class JavaStructProcessor extends Processor {

	String struct_layout, struct_body_getter_layout, struct_body_setter_layout, struct_constructor_body_layout,
			struct_variable_layout;

	public JavaStructProcessor() throws IOException {
		super();
		
		struct_layout = read("struct.layout");
		struct_variable_layout = read("struct_variable.layout");
		struct_body_getter_layout = read("struct_body_getter.layout");
		struct_body_setter_layout = read("struct_body_setter.layout");
		struct_constructor_body_layout = read("struct_constructor_body.layout");
		struct_variable_layout = read("struct_variable.layout");
	}

	public void process(Map<String, Object> attr) throws ProcessException {
		String strbuf = "";
		
		String structName = (String)attr.get("struct_name");
		List<Map<String, Object>> variables = (List<Map<String, Object>>)attr.get("variables");
		
		strbuf = copyOfString(struct_layout);
		strbuf = strbuf.replaceAll("%namespace%", getNamespace());
		strbuf = strbuf.replaceAll("%struct_variable.layout%", getStructVariable(variables));
		strbuf = strbuf.replaceAll("%struct_name%", structName);
		strbuf = strbuf.replaceAll("%arguments.layout%", getStructConstructorArgs(variables));
		strbuf = strbuf.replaceAll("%struct_constructor_body.layout%", getStructConstructorBody(variables));
		strbuf = strbuf.replaceAll("%struct_body_setter.layout%", getStructBodySetter(variables));
		strbuf = strbuf.replaceAll("%struct_body_getter.layout%", getStructBodyGetter(variables));
		
		write(strbuf, structName);
	}
	
	private String getStructVariable(List<Map<String, Object>> attr) {
		StringBuffer strbuf = new StringBuffer(1024);
		for(Map<String, Object> m : attr) {
			String copy = copyOfString(struct_variable_layout);
			copy = copy.replaceAll("%variable_type%", toJavaType((String)m.get("var_type")));
			copy = copy.replaceAll("%variable_name%", (String)m.get("var_name"));
			strbuf.append(copy).append("\n");
		}
		return strbuf.toString();
	}
	
	private String getStructConstructorArgs(List<Map<String, Object>> attr) {
		StringBuffer strbuf = new StringBuffer(256);
		for(Map<String, Object> m : attr) {
			String copy = copyOfString(arguments_layout);
			copy = copy.replaceAll("%arg_type%", toJavaType((String)m.get("var_type")));
			copy = copy.replaceAll("%arg_name%", (String)m.get("var_name"));
			strbuf.append(copy).append(", ");
		}
		return strbuf.substring(0, strbuf.length()-2);
	}
	
	private String getStructConstructorBody(List<Map<String, Object>> attr) {
		StringBuffer strbuf = new StringBuffer(256);
		for(Map<String, Object> m : attr) {
			String copy = copyOfString(struct_constructor_body_layout);
			copy = copy.replaceAll("%arg_name%", (String)m.get("var_name"));
			strbuf.append(copy).append("\n");
		}
		return strbuf.toString();
	}
	
	private String getStructBodySetter(List<Map<String, Object>> attr) {
		StringBuffer strbuf = new StringBuffer(256);
		for(Map<String, Object> m : attr) {
			String copy = copyOfString(struct_body_setter_layout);
			
			String varName = (String)m.get("var_name");
			char c = Character.toUpperCase(varName.charAt(0));
			String title = c + varName.substring(1, varName.length());
			
			copy = copy.replace("%setter_name%", title);
			copy = copy.replaceAll("%variable_name%", varName);
			copy = copy.replaceAll("%variable_type%", toJavaType((String)m.get("var_type")));
			strbuf.append(copy).append("\n");
		}
		return strbuf.toString();
	}
	
	private String getStructBodyGetter(List<Map<String, Object>> attr) {
		StringBuffer strbuf = new StringBuffer(256);
		for(Map<String, Object> m : attr) {
			String copy = copyOfString(struct_body_getter_layout);
			
			String varName = (String)m.get("var_name");
			char c = Character.toUpperCase(varName.charAt(0));
			String title = c + varName.substring(1, varName.length());
			
			copy = copy.replaceAll("%getter_name%", title);
			copy = copy.replaceAll("%variable_name%", varName);
			copy = copy.replaceAll("%variable_type%", toJavaType((String)m.get("var_type")));
			strbuf.append(copy).append("\n");
		}
		return strbuf.toString();
	}
	
	private String toJavaType(String type) {
		return StringUtils.toJavaType(type, getNamespace());
	}
}
